package com.sinszm.sofa;

import cn.hutool.core.lang.Assert;
import com.sinszm.sofa.exception.ApiException;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import org.redisson.client.codec.BaseCodec;
import org.redisson.codec.SerializationCodec;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;

/**
 * 订阅发布工具
 *
 * @author admin
 */
@Component
public class SubUtil<T extends Serializable> {

    @Resource
    private RedissonClient redissonClient;

    /**
     * 订阅
     *
     * @param topicName  主题名称
     * @param topicClass 主题类
     * @param message    消息
     */
    public void subscribe(String topicName, Class<T> topicClass, MessageListener<T> message) {
        subscribe(topicName, topicClass, message, new SerializationCodec());
    }

    /**
     * 订阅
     *
     * @param topicName  主题名称
     * @param topicClass 主题类
     * @param message    消息
     * @param codec      编解码器
     */
    public void subscribe(String topicName, Class<T> topicClass, MessageListener<T> message, BaseCodec codec) {
        Assert.notEmpty(topicName, () -> new ApiException("-1", "消息主题不能为空"));
        Assert.notNull(topicClass, () -> new ApiException("-1", "消息数据序列类不能为空"));
        Assert.notNull(message, () -> new ApiException("-1", "订阅消息处理器不能为空"));
        RTopic topic = redissonClient.getTopic(topicName,codec == null ? new SerializationCodec() : codec);
        topic.addListener(topicClass, message);
    }

    /**
     * 发布
     *
     * @param topicName 主题名称
     * @param data      数据
     * @return long     收到消息的客户端数量
     */
    public long publish(String topicName, T data) {
        return publish(topicName, data, new SerializationCodec());
    }

    /**
     * 发布
     *
     * @param topicName 主题名称
     * @param data      数据
     * @param codec     编解码器
     * @return long     收到消息的客户端数量
     */
    public long publish(String topicName, T data, BaseCodec codec) {
        Assert.notEmpty(topicName, () -> new ApiException("-1", "消息主题不能为空"));
        Assert.notNull(data, () -> new ApiException("-1", "发布消息数据不能为空"));
        RTopic topic = redissonClient.getTopic(topicName, codec == null ? new SerializationCodec() : codec);
        return topic.publish(data);
    }

}
